/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef UTILITY_FILE_UTIL_H
#define UTILITY_FILE_UTIL_H

#include <string>
#include <vector>
#include <functional>

namespace El {
namespace Utils {

bool LoadBufferFromFile(const std::string &filePath, std::vector<uint8_t> &content);

bool SaveBufferToFile(const std::string &filePath, const std::vector<uint8_t> &content, bool truncated /*= true*/);

std::string ExtractFilePath(const std::string &fileFullName);

std::string ExtractFileName(const std::string &fileFullName);

void SyncFile(const std::string &dst);

// 创建目录,支持递归创建多级目录
bool CreateDirectories(const std::string &path);

// 检查文件是否存在
bool IsFileExists(const std::string &path);

/**
 * @brief 检查目录是否存在
 * @param path 目录路径
 * @return 如果目录存在返回true，否则返回false
 */
bool IsDirectoryExists(const std::string &path);

/**
 * @brief 检查文件是否正在被使用
 * @param filePath 文件路径
 * @return true 文件正在被使用，false 文件未被使用
 * @note 通过尝试以独占方式打开文件来检查
 */
bool IsFileInUse(const std::string &filePath);

/**
 * @brief 遍历目录中的所有文件
 * @param path 目录路径
 * @param callback 处理每个文件的回调函数，接收文件名作为参数
 *                 如果回调返回false，遍历将终止
 * @return 遍历成功返回true，失败返回false
 */
bool TraverseDirectory(const std::string &path, const std::function<bool(const std::string &)> &callback);

/**
 * @brief 保存文件并创建备份
 * @param filePath 目标文件路径
 * @param content 要保存的内容
 * @return 是否保存成功
 * @note 该函数会先写入主文件并同步，然后写入隐藏备份文件并同步
 */
bool SaveFileWithBackup(const std::string &filePath,
                        const std::vector<uint8_t> &content,
                        const std::string &backupSuffix = ".bak");

/**
 * @brief 读取文件，如果主文件损坏则从备份恢复
 * @param filePath 文件路径
 * @param content 输出参数，存储读取的内容
 * @return 是否读取成功
 * @note 先读取主文件并验证JSON格式，如果失败则尝试读取隐藏备份文件
 */
bool LoadFileWithBackup(const std::string &filePath,
                        std::vector<uint8_t> &content,
                        const std::string &backupSuffix = ".bak");

} // namespace Utils
} // namespace El

#endif // UTILITY_FILE_UTIL_H